package top.yangbuyi.system.controller;

import com.google.gson.Gson;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.yangbuyi.system.common.*;
import top.yangbuyi.system.config.QQ.OAuthProperties;
import top.yangbuyi.system.config.QQ.vo.QQDTO;
import top.yangbuyi.system.config.QQ.vo.QQOpenidDTO;
import top.yangbuyi.system.domain.Loginfo;
import top.yangbuyi.system.domain.User;
import top.yangbuyi.system.service.LoginfoService;
import top.yangbuyi.system.service.RoleService;
import top.yangbuyi.system.service.UserService;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * description:  杨不易网站 :www.yangbuyi.top
 * program:  yangbuyi-erp-2020
 * ClassName:  QQController
 * create:  2020-06-24 17:17
 *
 * @author: yangbuyi
 * @since： JDK1.8
 **/

@RestController
@RequestMapping("api")
public class QQController {
      
      @Autowired
      private OAuthProperties oauth;
      private static final Logger logger = LoggerFactory.getLogger(QQController.class);
      @Autowired
      private OAuthProperties qqProperties;
      @Autowired
      private LoginfoService loginfoService;
      @Autowired
      private UserService userService;
      @Autowired
      private RoleService roleService;
      
      /**
       * 调用QQ登陆接口
       *
       * @param response
       */
      @GetMapping("/login/oauth")
      public String loginQQ(HttpServletResponse response) {
            /**
             * 重定向
             */
//                  response.sendRedirect();//授权模式，授权码模式
            
            System.out.println(
                  oauth.getQQ().getCode_callback_uri() + //获取code码地址
                        "?client_id=" + oauth.getQQ().getClient_id()//appid
                        + "&state=" + UUID.randomUUID() + //这个说是防攻击的，就给个随机uuid吧
                        "&redirect_uri=" + oauth.getQQ().getRedirect_uri() +//这个很重要，这个是回调地址，即就收腾讯返回的code码
                        "&response_type=code"
            );
            
            return oauth.getQQ().getCode_callback_uri() + //获取code码地址
                  "?client_id=" + oauth.getQQ().getClient_id()//appid
                  + "&state=" + UUID.randomUUID() + //这个说是防攻击的，就给个随机uuid吧
                  "&redirect_uri=" + oauth.getQQ().getRedirect_uri() +//这个很重要，这个是回调地址，即就收腾讯返回的code码
                  "&response_type=code";
            
            
      }
      
      
      //接收回调地址带过来的code码
      @GetMapping("/oauth2")
      public void authorizeQQ(Map<String, String> msg, String code, HttpServletResponse response) {
            HashMap<String, Object> params = new HashMap<>();
            params.put("code", code);
            params.put("grant_type", "authorization_code");
            params.put("redirect_uri", oauth.getQQ().getRedirect_uri());
            params.put("client_id", oauth.getQQ().getClient_id());
            params.put("client_secret", oauth.getQQ().getClient_secret());
            //获取access_token如：access_token=9724892714FDF1E3ED5A4C6D074AF9CB&expires_in=7776000&refresh_token=9E0DE422742ACCAB629A54B3BFEC61FF
            String result = HttpsUtils.doGet(oauth.getQQ().getAccess_token_callback_uri(), params);
            //对拿到的数据进行切割字符串
            String[] strings = result.split("&");
            //切割好后放进map
            Map<String, String> reulsts = new HashMap<>();
            for (String str : strings) {
                  String[] split = str.split("=");
                  if (split.length > 1) {
                        reulsts.put(split[0], split[1]);
                  }
            }
            //到这里access_token已经处理好了
            //下一步获取openid，只有拿到openid才能拿到用户信息
            String openidContent = HttpsUtils.doGet(oauth.getQQ().getOpenid_callback_uri() + "?access_token=" + reulsts.get("access_token"));
            //接下来对openid进行处理
            //截取需要的那部分json字符串
            String openid = openidContent.substring(openidContent.indexOf("{"), openidContent.indexOf("}") + 1);
            Gson gson = new Gson();
            //将返回的openid转换成DTO
            QQOpenidDTO qqOpenidDTO = gson.fromJson(openid, QQOpenidDTO.class);
            
            //接下来说说获取用户信息部分
            //登陆的时候去数据库查询用户数据对于openid是存在，如果存在的话，就不用拿openid获取用户信息了，而是直接从数据库拿用户数据直接认证用户，
            // 否则就拿openid去腾讯服务器获取用户信息，并存入数据库，再去认证用户
            //下面关于怎么获取用户信息，并登陆
            params.clear();
            params.put("access_token", reulsts.get("access_token"));//设置access_token
            params.put("openid", qqOpenidDTO.getOpenid());//设置openid
            params.put("oauth_consumer_key", qqOpenidDTO.getClient_id());//设置appid
            //获取用户信息
            String userInfo = HttpsUtils.doGet(oauth.getQQ().getUser_info_callback_uri(), params);
            QQDTO qqDTO = gson.fromJson(userInfo, QQDTO.class);
            //这里拿用户昵称，作为用户名，openid作为密码（正常情况下，在开发时候用openid作为用户名，再自己定义个密码就可以了）
            String token = "";
            try {
                  // 这里进行 QQ登陆用户 添加新的用户
                  // 设置用户基本信息
                  User user1 = this.userService.queryUserByLoginName(qqDTO.getNickname());
                  
                  
                  if (user1 == null) {
                        User user = new User();
                        user.setName(qqDTO.getNickname());
                        user.setLoginname(qqDTO.getNickname());
                        user.setSalt(MD5Utils.createUUID());
                        user.setType(Constant.USER_TYPE_NORMAL);
                        user.setPwd(MD5Utils.md5(Constant.DEFAULT_PWD, user.getSalt(), 2));
                        user.setSex(qqDTO.getGendertype());
                        user.setAvailable(Constant.AVAILABLE_TRUE);
                        user.setImgpath(qqDTO.getFigureurl_qq_2());
                        user.setRemark("QQ登陆-" + qqDTO.getNickname());
                        user.setAddress(qqDTO.getProvince() + "-" + qqDTO.getCity());
                        user.setDeptid(44);
                        user.setHiredate(new Date());
                        user.setOrdernum(this.userService.queryUserMaxOrderNum() + 1);
                        // 进行保存用户
                        this.userService.saveUser(user);
                        
                        
                        // 查询用户
                        User user2 = this.userService.queryUserByLoginName(qqDTO.getNickname());
                        /**
                         * 保存角色
                         */
                        this.userService.saveUserRole(user2.getId(), Constant.QQ_ROLE_DEFAULT);
                        System.out.println(user);
                  }else{
                        // 如果已经有用户了  重新录入头像
                        user1.setName(qqDTO.getNickname());
                        user1.setLoginname(qqDTO.getNickname());
                        user1.setSex(qqDTO.getGendertype());
                        user1.setImgpath(qqDTO.getFigureurl_qq_2());
                        user1.setRemark("QQ登陆-" + qqDTO.getNickname());
                        user1.setAddress(qqDTO.getProvince() + "-" + qqDTO.getCity());
                        this.userService.updateUser(user1);
                  }
                  
                 
                  
                  System.out.println("用户信息:" + userInfo);
                  System.out.println(qqDTO);
                  // 获取主体
                  Subject subject = SecurityUtils.getSubject();
//                  SecurityUtils.getSubject().login(new UsernamePasswordToken(qqOpenidDTO.getOpenid(), Constant.DEFAULT_PWD));
                  System.out.println(qqOpenidDTO.getOpenid());
                  
                  // 进行Shiro认证
                  subject.login(new UsernamePasswordToken(qqDTO.getNickname(), Constant.DEFAULT_PWD));
                  
                  token = subject.getSession().getId().toString();
                  ActiveUser active = (ActiveUser) subject.getPrincipal();
                  
                  /* 写入登陆日志开始 */
                  Loginfo loginfo = new Loginfo();
                  String remoteAddr = WebUtils.getHttpServletRequest().getHeader("X-Forwarded-For");
                  loginfo.setLoginip(remoteAddr);
                  loginfo.setLoginname(qqDTO.getNickname());
                  loginfo.setLogintime(new Date());
                  loginfoService.save(loginfo);
                  /* 写入登陆日志结束 */
                  
                  params.put("token", token);
                  params.put("code", 200);
                  params.put("permissions", active.getPermissions());
                  params.put("username", active.getUser().getName());
                  params.put("usertype", active.getUser().getType());
                  System.out.println("Shiro认证成功");
                  System.out.println(token);
                  response.sendRedirect(qqProperties.getQQ().getRedirect_url_index_yby() + "?token=" + token);
            } catch (Exception e) {
                  msg.put("msg", "第三方登陆失败,请联系管理！");
                  e.printStackTrace();
                  logger.error(e.getMessage());
                  System.out.println("Shiro认证失败");
//                  return new ResultObj(-1, "login.html");
//                  return "redirect:https://www.yangbuyi.top/login.html";
                  try {
                        response.sendRedirect(qqProperties.getQQ().getRedirect_url_login_yby());
                  } catch (IOException e1) {
                        e1.printStackTrace();
                  }
                  
            }
      }
      
      /**
       * 获取参数
       *
       * @return
       */
      @RequestMapping("getParams")
      public Object getParams() {
            Subject subject = SecurityUtils.getSubject();
            ActiveUser active = (ActiveUser) subject.getPrincipal();
            Map<String, Object> map = new HashMap<>();
            map.put("permissions", active.getPermissions());
            map.put("username", active.getUser().getName());
            map.put("usertype", active.getUser().getType());
            return map;
      }
      
      
}
